home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dcc / main.c < prev    next >
C/C++ Source or Header  |  1997-09-09  |  47KB  |  2,386 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6.  
  7. /*
  8.  *  MAIN.C
  9.  *
  10.  *  dcc <options> <files>
  11.  */
  12.  
  13. #include "defs.h"
  14. #ifdef COMMERCIAL
  15. #ifndef unix
  16. #include <lib/rexx.h>
  17. #endif
  18. #endif
  19.  
  20. #ifndef AZLAT_COMPAT
  21. #define DoLink_Dice    DoLink
  22. #define DoCompile_Dice    DoCompile
  23. #define DoAssemble_Dice DoAssemble
  24. #define DoPrelink_Dice    DoPrelink
  25. #endif
  26.  
  27. #include "DCC_rev.h"
  28.  
  29. static char *DCopyright =
  30. "Copyright (c) 1992,1993,1994 Obvious Implementations Corp., Redistribution & Use under DICE-LICENSE.TXT." VERSTAG;
  31.  
  32.  
  33. Prototype   void    myexit(void);
  34. Prototype   int     main(int, char **);
  35. Prototype   void    AddFile(char *);
  36. Prototype   void    help(int);
  37. Prototype   char    *TmpFileName(char *);
  38. Prototype   char    *MungeFile(char *, char *, char *);
  39. Prototype   void    AddName(List *, char *, char *, short);
  40. Prototype   struct NameNode *AddOpt(List *, char *, char *);
  41. Prototype   char    *Tailer(char *);
  42. Prototype   char    *XFilePart(char *);
  43. Prototype   char    *OptListToStr(List *);
  44. Prototype   char    *OptListToStr2(List *, char *);
  45. Prototype   void    run_cmd(char *, char *);
  46. Prototype   int     OutOfDate(char *, char *);
  47. Prototype   void    HandleCFile(struct NameNode *, int);
  48. Prototype   void    HandleAFile(struct NameNode *, int);
  49. Prototype   void    PushTmpFile(char *);
  50. Prototype   void    PopTmpFile(char *);
  51. Prototype   long    LoadSegLock(long, char *);
  52. Prototype   void    DefaultOutName(void);
  53.  
  54. Prototype   int     DoCompile(char *, char *);
  55. Prototype   int     DoCompile_Dice(char *, char *);
  56. Prototype   int     DoCompile_Aztec(char *, char *);
  57. Prototype   int     DoCompile_Lattice(char *, char *);
  58. Prototype   int     DoAssemble(char *, char *, char *);
  59. Prototype   int     DoAssemble_Dice(char *, char *, char *);
  60. Prototype   int     DoAssemble_Aztec(char *, char *, char *);
  61. Prototype   int     DoAssemble_Lattice(char *, char *, char *);
  62. Prototype   char    *DoPrelink(void);
  63. Prototype   char    *DoPrelink_Dice(void);
  64. Prototype   char    *DoPrelink_Aztec(void);
  65. Prototype   char    *DoPrelink_Lattice(void);
  66. Prototype   int     DoLink(char *);
  67. Prototype   int     DoLink_Dice(char *);
  68. Prototype   int     DoLink_Aztec(char *);
  69. Prototype   int     DoLink_Lattice(char *);
  70. Prototype   char    *PathConvert(char *);
  71. Prototype   void    *GetHead(List *);
  72. Prototype   void    *GetSucc(Node *);
  73. Prototype   void    FlushStoredErrors(char *cfile);
  74. Prototype   int     HandleErrorRexx(char *, char *, int);
  75. Prototype   char    *ScanReplace(char *, char *, char *, char *);
  76. Prototype   char    *FullPathOf(char *);
  77. Prototype   char    *mergestr(const char *s1, const char *s2);
  78.  
  79. Prototype   void    eprintf(const char *ctl, ...);
  80.  
  81. void OrderApp(char *);
  82. void AddLibApp(char *, char);
  83. void DelLibApp(char *, char);
  84. void uexit(int code);
  85.  
  86. /*
  87.  *  Note that we use exec_dcc if DCC, which only works with 'dcc' programs
  88.  *  thus, the executables are renamed to prevent problems.
  89.  */
  90.  
  91. Prototype __aligned char Buf[512];
  92. Prototype __aligned char CmdName[64];
  93.  
  94.  
  95. __aligned char Buf[512];
  96. __aligned char CmdName[64];
  97. char TmpFile[64];
  98. char ErrOptStr[128];
  99. char *ErrFile;
  100. FILE *ErrorFi;
  101. char *OutFile;
  102. char *OutDir = NULL;
  103. #ifdef AMIGA
  104. char *TmpDir = "T:";
  105. #else
  106. char *TmpDir = "/tmp/";
  107. #endif
  108. char *DLib;
  109. char *AmigaLib;
  110. char *CLib;
  111. char ALibOS[4];
  112. char ALibApp[32] = { "s" };
  113. char CLibApp[32] = { "s" };
  114. char *RexxReplace[10];
  115. List TmpList;
  116. short dasAddSym;
  117. short ErrFileIsTmp;
  118. short NewOpt;
  119. short FastOpt;
  120. short FragOpt;
  121. short ChipOpt;
  122. short MC68020Opt;
  123. short MC68881Opt;
  124. short FFPOpt;
  125. short DDebug;
  126. short RegCallOpt;
  127. short NoHeirOpt;
  128. short NoEnvOpt;
  129. short NoCtlOpt;
  130. short SlashSlashOpt;
  131. short ProfOpt;
  132. short DLinkPostFixOpt;
  133. short UnixOpt;
  134. short UnixRCOpt;
  135. short ForkOpt;
  136. short UnixCommonOpt;
  137. short InlineCompOpt;
  138. short RexxOpt;
  139.  
  140. long    ExitCode;
  141.  
  142. char DLINK[32];
  143. char DAS[32];
  144. char DC1[32];
  145. char DCPP[32];
  146.  
  147. char *RexxHostName = "DCC";
  148.  
  149. char *SCode[4];
  150. char *IntOpt = "";
  151.  
  152.  
  153. typedef struct NameNode {
  154.     struct Node n_Node;
  155.     char    *n_In;
  156.     char    *n_Out;
  157.     short   n_IsType;
  158. } NameNode;
  159.  
  160. #define IS_CFILE    1
  161. #define IS_AFILE    2
  162. #define IS_OFILE    3
  163. #define IS_LIBFILE  4
  164. #define IS_TMP        0x100
  165. #define IsMask(istype) ((ubyte)istype)
  166.  
  167. List   FList;
  168. List   LList;
  169.  
  170. List   CppOptList;
  171. List   LinkOptList;
  172.  
  173. short    NoLink;
  174. short    NoAsm;
  175. short    SmallCode = 1;
  176. short    SmallData = 1;
  177. short    ConstCode;        /*    -ms            */
  178. short    AbsData;        /*    -mw, -ma        */
  179. short    ResOpt;
  180. short    AltSectOpt;
  181. short    SymOpt;
  182. short    RomOpt;
  183. short    ProtoOnlyOpt;
  184. short    NoIntermediateAssembly;
  185. short    PIOpt;
  186. short    GenStackOpt;
  187. short    GenLinkOpt;
  188. short    Verbose;
  189. short    NoDefaultLibs;
  190. short    CompilerOpt = DICE_C;
  191. long    AbsDataStart;        /*    -mw <addr>  */
  192. char    DebugOpts[64];
  193.  
  194. NameNode *InlineNode;
  195.  
  196. extern struct Library *SysBase;
  197.  
  198. void
  199. myexit()
  200. {
  201.     Node *node;
  202.  
  203.     while ((node = RemHead(&TmpList)) != NULL) {
  204.     remove(node->ln_Name);
  205.     free(node);
  206.     }
  207.     if (ErrFileIsTmp) {
  208.     if (ErrorFi) {
  209.         fclose(ErrorFi);
  210.         ErrorFi = NULL;
  211.     }
  212.     remove(ErrFile);
  213.     }
  214. }
  215.  
  216. int
  217. main(xac, xav)
  218. int xac;
  219. char *xav[];
  220. {
  221.     int fc = 0;
  222.     int ac;
  223.     char **av;
  224.  
  225.  
  226. #ifdef LATTICE
  227.     {
  228.     long n = (long)Buf;
  229.     if (n & 3) {
  230.         puts("software error, Buf not aligned");
  231.         uexit(25);
  232.     }
  233.     }
  234. #endif
  235. #ifdef NOTDEF
  236.     expand_args(xac, xav, &ac, &av);
  237. #else
  238.     ac = xac;
  239.     av = xav;
  240. #endif
  241.  
  242.     NewList(&FList);
  243.     NewList(&LList);
  244.  
  245.     NewList(&TmpList);
  246.  
  247.     NewList(&CppOptList);
  248.     NewList(&LinkOptList);
  249.  
  250.     atexit(myexit);
  251.  
  252.     if (ac == 1)
  253.     help(0);
  254.  
  255.     {
  256.     char *ptr = av[0];    /*  cmd name */
  257.     char prefix[32];
  258.     short i;
  259.  
  260.     for (i = strlen(ptr); i >= 0 && ptr[i] != ':' && ptr[i] != '/'; --i);
  261.     ++i;
  262.  
  263.     ptr = ptr + i;        /*  base name */
  264.     for (i = 0; ptr[i] && ptr[i] != '_'; ++i);
  265.     if (ptr[i] == '_') {
  266.         strncpy(prefix, ptr, i + 1);
  267.         prefix[i+1] = 0;
  268.     } else {
  269.         prefix[0] = 0;
  270.     }
  271.     sprintf(DLINK, "%s%s", prefix, "dlink");
  272.     sprintf(DAS  , "%s%s", prefix, "das");
  273.     sprintf(DC1  , "%s%s", prefix, "dc1");
  274.     sprintf(DCPP , "%s%s", prefix, "dcpp");
  275.     DLib = mergestr(DLIBPRE, prefix);
  276.     DLib = mergestr(DLib, DLIBPOS);
  277.     }
  278.     AmigaLib = mergestr(DLib, "amiga");
  279.     CLib = mergestr(DLib, "c");
  280.  
  281.     /*
  282.      *  2 x PIOpt + ResOpt
  283.      */
  284.  
  285.     SCode[0] = mergestr(DLib, "c.o");
  286.     SCode[1] = mergestr(DLib, "c.o");
  287.     SCode[2] = mergestr(DLib, "c_pi.o");
  288.     SCode[3] = mergestr(DLib, "c_pr.o");
  289.  
  290.     /*
  291.      *    check for -no-env option before processing DCCOPTS enviroment var
  292.      *    check for -no-ctl option before processing DCCOPTS file
  293.      */
  294.  
  295.     {
  296.     long i;
  297.  
  298.     for (i = 1; i < ac; ++i) {
  299.         if (strcmp(av[i], "-no-env") == 0) {
  300.         NoEnvOpt = 1;
  301.         break;
  302.         }
  303.         if (strcmp(av[i], "-no-ctl") == 0) {
  304.         NoCtlOpt = 1;
  305.         break;
  306.         }
  307.     }
  308.     }
  309.  
  310.     if (NoEnvOpt == 0) {
  311.     char **argv = av;
  312.     ac = ExtArgsEnv(ac, &argv, "DCCOPTS");
  313.     av = argv;
  314.     }
  315.  
  316.     if (NoCtlOpt == 0) {
  317.     char **argv = av;
  318.     ac = ExtArgsFile(ac, &argv, "DCCOPTS");
  319.     av = argv;
  320.     }
  321.  
  322.     {
  323.     long i;
  324.     char *dummy;
  325.  
  326.     for (i = 1; i < ac; ++i) {
  327.         char *ptr = av[i];
  328.  
  329.         if (*ptr == '-') {
  330.         ptr += 2;
  331.  
  332.         switch(ptr[-1]) {
  333.         case '0':       /*  -020/-030/-040      */
  334.             MC68020Opt = 1;
  335.             break;
  336.         case '1':       /*  1.4, 1.3    */
  337.         case '2':       /*  2.0, 2.1..  */
  338.         case '3':
  339.         case '4':
  340.         case '5':
  341.             if (ptr[0] != '.')
  342.             help(1);
  343.             AddOpt(&CppOptList, ptr - 2, "");
  344.             ALibOS[0] = ptr[-1];
  345.             ALibOS[1] = ptr[1];
  346.             break;
  347.         case '8':
  348.             MC68881Opt = 1;
  349.             break;
  350.         case 'f':
  351.             if (*ptr == 0)
  352.             FastOpt = 1;
  353.             else if (*ptr == '0')
  354.             FastOpt = 0;
  355.             else if (*ptr == 'r') {
  356.             if (stricmp(ptr, "rag0") == 0)
  357.                 FragOpt = 0;
  358.             else
  359.                 FragOpt = 1;
  360.             } else if (*ptr == 'f')
  361.             FFPOpt = 1;
  362.             else if (*ptr == 'o') {
  363.             ForkOpt = 1;
  364.             AddLibApp(CLibApp, 'f');
  365.             }
  366.             break;
  367.         case 'i':   /*  -ieee   */
  368.             if (*ptr == 'e')
  369.             FFPOpt = 0;
  370.             else if (strncmp(ptr, "nt", 2) == 0) {
  371.             IntOpt = (ptr[2]) ? ptr + 2 : av[++i];
  372.             }
  373.             break;
  374.         case 'r':
  375.             if (strcmp(ptr, "om") == 0) {
  376.             RomOpt = 1;
  377.             } else if (*ptr == '0') {
  378.             ResOpt = 0;
  379.             } else {
  380.             if (PIOpt && ResOpt == 0)
  381.                 puts("DCC: Warning, -r -pi = -pr");
  382.             ResOpt = 1;
  383.             }
  384.             break;
  385.         case 'c':
  386.             if (*ptr == 0)
  387.             NoLink = 1;
  388.             else if (stricmp(ptr, "hip") == 0)
  389.             ChipOpt = 1;
  390.             else if (stricmp(ptr, "hip0") == 0)
  391.             ChipOpt = 0;
  392.             else
  393.             help(1);
  394.             break;
  395.         case 'a':
  396.             if (strcmp(ptr, "ztec") == 0) {
  397.             CompilerOpt = AZTEC_C;
  398.             break;
  399.             }
  400.             NoAsm = 1;
  401.             NoLink= 1;
  402.             break;
  403.         case 'g':
  404.             switch (*ptr) {
  405.             case 's':
  406.             GenStackOpt = 1;
  407.             if (ptr[1] == '0')
  408.                 GenStackOpt = 0;
  409.             break;
  410.             case 'l':
  411.             GenLinkOpt = 1;
  412.             break;
  413.             default:
  414.             help(1);
  415.             }
  416.             break;
  417.         case 'l':
  418.             if (strcmp(ptr, "attice") == 0) {
  419.             CompilerOpt = LATTICE_C;
  420.             break;
  421.             }
  422.             if (ptr[0] == '0' && ptr[1] == 0) {
  423.             NoDefaultLibs = 1;
  424.             break;
  425.             }
  426.             if (*ptr == 0)
  427.             ptr = av[++i];
  428.             AddName(&LList, ".lib", ptr, IS_LIBFILE);
  429.             DLinkPostFixOpt = 1;
  430.             break;
  431.         case 'L':   /*  -Ldir   */
  432.             if (ptr[0] == '0' && ptr[1] == 0) {
  433.             AddOpt(&LinkOptList, "-L0", "");
  434.             break;
  435.             }
  436.             if (*ptr == 0)
  437.             ptr = av[++i];
  438.             AddOpt(&LinkOptList, "-L", PathConvert(ptr));
  439.             break;
  440.         case 'I':   /*  -Idir   */
  441.             if (ptr[0] == '0' && ptr[1] == 0) {
  442.             AddOpt(&CppOptList, "-I0", "");
  443.             break;
  444.             }
  445.             if (*ptr == 0)
  446.             ptr = av[++i];
  447.             AddOpt(&CppOptList, "-I", PathConvert(ptr));
  448.             break;
  449.         case 'd':   /*  -dice -d<n> -d<debug_opts>  */
  450.             /*
  451.              *    note that -d<n> and -s<n> are mutually
  452.              *    exclusive in that -d1 implies -s and -s0
  453.              *    implies -d0
  454.              */
  455.  
  456.             if (strcmp(ptr, "ice") == 0) {
  457.             CompilerOpt = DICE_C;
  458.             break;
  459.             }
  460.             sprintf(DebugOpts, " -d%s", ptr);
  461.  
  462. #ifdef LATTICE
  463.             switch(atoi(ptr)) {
  464. #else
  465.             switch(strtol(ptr, NULL, 0)) {
  466. #endif
  467.             case 0:
  468.             SymOpt = 0;
  469.             break;
  470.             default:
  471.             SymOpt = 1;
  472.             }
  473.             break;
  474.         case 'Z':
  475.             if (atoi(ptr)) {
  476.             DDebug = atoi(ptr);
  477.             break;
  478.             }
  479.             break;
  480.         case 'D':   /*  -Ddefine[=str] */
  481.             if (*ptr == 0)
  482.             ptr = av[++i];
  483.             AddOpt(&CppOptList, "-D", ptr);
  484.             break;
  485.         case 'H':   /*  -H<path>=<include_name>    */
  486.             if (*ptr == 0)
  487.             ptr = av[++i];
  488.             AddOpt(&CppOptList, "-H", ptr);
  489.             break;
  490.         case 'u':
  491.             if (strcmp(ptr, "nixrc") == 0) {
  492.             UnixRCOpt = 1;
  493.             } else if (strcmp(ptr, "nix") == 0) {
  494.             UnixOpt = 1;
  495.             CLib = mergestr(DLib, "uc");
  496.             AddOpt(&CppOptList, "-unix", "");
  497.             }
  498.             break;
  499.         case 'U':   /*  -U      -undefine certain symbols */
  500.             AddOpt(&CppOptList, "-U", ptr);
  501.             break;
  502.         case 'o':
  503.             if (*ptr)
  504.             OutFile = PathConvert(ptr);
  505.             else
  506.             OutFile = PathConvert(av[++i]);
  507.             {
  508.             short idx = strlen(OutFile) - 2;
  509.             if (idx >= 0) {
  510.                 if (stricmp(OutFile + idx, ".h") == 0 || stricmp(OutFile + idx, ".c") == 0) {
  511.                 puts("ERROR! -o output file may not end in .c or .h!");
  512.                 uexit(20);
  513.                 }
  514.             }
  515.             }
  516.             break;
  517.         case 'O':
  518.             if (strcmp(ptr, "0") == 0)
  519.             OutDir = NULL;
  520.             else if (*ptr)
  521.             OutDir = PathConvert(ptr);
  522.             else
  523.             OutDir = PathConvert(av[++i]);
  524.             break;
  525.         case 'E':   /*  error output append */
  526.             {
  527.             char errtype = '1';
  528.             if (*ptr >= '1' && *ptr <= '9')
  529.             {
  530.                 errtype = *ptr;
  531.                 ptr++;
  532.             }
  533.             if (*ptr == 0)
  534.             ptr = av[++i];
  535.  
  536.             if ((ErrorFi = fopen(ptr, "a")) != NULL) {
  537.                 if (ErrFile)
  538.                 remove(ErrFile);
  539.                 ErrFile = ptr;
  540.                 ErrFileIsTmp = 0;
  541.                 sprintf(ErrOptStr, " -E%c %s", errtype, ptr);
  542.             } else {
  543.                 printf("unable to append to %s\n", ptr);
  544.             }
  545.             }
  546.             break;
  547.         case 'p':
  548.             if (strcmp(ptr, "roto") == 0) {
  549.             ProtoOnlyOpt = 1;
  550.             } else if (strncmp(ptr, "rof", 3) == 0) {
  551.             if (ptr[3] != '0') {
  552.                 ProfOpt = atoi(ptr + 3);
  553.                 if (ProfOpt == 0)
  554.                 ProfOpt = 1;
  555.                 if (ProfOpt >= 2)
  556.                 AddLibApp(CLibApp, 'p');
  557.                 if (ProfOpt >= 3)
  558.                 AddLibApp(ALibApp, 'p');
  559.             } else {
  560.                 ProfOpt = 0;
  561.                 DelLibApp(ALibApp, 'p');
  562.                 DelLibApp(CLibApp, 'p');
  563.             }
  564.             } else if (strcmp(ptr, "i") == 0) {
  565.             PIOpt = 1;
  566.             if (ResOpt)
  567.                 puts("DCC: Warning, -r -pi = -pr");
  568.             } else if (strcmp(ptr, "r") == 0) {
  569.             PIOpt = 1;
  570.             ResOpt = 1;
  571.             } else {
  572.             help(1);
  573.             }
  574.             break;
  575.         case 'T':
  576.             if (*ptr)
  577.             TmpDir = PathConvert(ptr);
  578.             else
  579.             TmpDir = PathConvert(av[++i]);
  580.             break;
  581.         case 'm':
  582.             switch(*ptr) {
  583.             case 'C':
  584.             SmallCode = 0;
  585.             break;
  586.             case 'c':
  587.             SmallCode = 1;
  588.             break;
  589.             case 'D':
  590.             SmallData = 0;
  591.             DelLibApp(ALibApp, 's');
  592.             DelLibApp(CLibApp, 's');
  593.             AddLibApp(ALibApp, 'l');
  594.             AddLibApp(CLibApp, 'l');
  595.             break;
  596.             case 'd':
  597.             SmallData = 1;
  598.             DelLibApp(ALibApp, 'l');
  599.             DelLibApp(CLibApp, 'l');
  600.             AddLibApp(ALibApp, 's');
  601.             AddLibApp(CLibApp, 's');
  602.             break;
  603.             case 'a':
  604.             case 'w':
  605.             if (ptr[1] == 'a') {
  606.                 AbsData = 0;
  607.                 AbsDataStart = 0;
  608.             } else {
  609.                 AbsData = 1;
  610.  
  611.                 if (*ptr == 'a')
  612.                 AbsData = 2;
  613.  
  614.                 ++ptr;
  615.                 if (*ptr == 0)
  616.                 ptr = av[++i];
  617.  
  618. #ifdef LATTICE
  619.                 AbsDataStart = atoi(ptr);    /*  bug in lattice */
  620. #else
  621.                 AbsDataStart = strtol(ptr, &dummy, 0);
  622. #endif
  623.             }
  624.             break;
  625.             case 'r':
  626.             RegCallOpt = 1;
  627.             break;
  628.             case 'R':
  629.             AddLibApp(CLibApp, 'r');
  630.             AddLibApp(ALibApp, 'r');
  631.  
  632.             RegCallOpt = 2;
  633.             if (ptr[1] == 'R') {
  634.                 ProtoOnlyOpt = -1;    /*  force prototypes */
  635.                 RegCallOpt = 3;
  636.  
  637.                 switch(ptr[2]) {
  638.                 case 'X':
  639.                 RegCallOpt = 4;
  640.                 break;
  641.                 case 'Y':
  642.                 RegCallOpt = 5;
  643.                 break;
  644.                 case '0':
  645.                 RegCallOpt = 0;
  646.                 DelLibApp(CLibApp, 'r');
  647.                 DelLibApp(ALibApp, 'r');
  648.                 if (ProtoOnlyOpt == -1)
  649.                     ProtoOnlyOpt = 0;
  650.                 break;
  651.                 }
  652.             }
  653.             break;
  654.             case 's':
  655.             if (ptr[1])
  656.                 ConstCode = ptr[1] - '0';
  657.             else
  658.                 ConstCode = 1;
  659.             break;
  660.             case 'S':
  661.             /* XXX REMOVED */
  662.             /*ConstCode = 2;*/
  663.             break;
  664.             case 'u':
  665.             UnixCommonOpt = 1;
  666.             break;
  667.             case 'i':
  668.             if (ptr[1] == '0') {
  669.                 if (InlineCompOpt && InlineNode) {
  670.                 InlineCompOpt = 0;
  671.                 Remove(&InlineNode->n_Node);
  672.                 InlineNode = NULL;
  673.                 }
  674.             } else {
  675.                 if (InlineCompOpt == 0) {
  676.                 InlineCompOpt = 1;
  677.                 InlineNode = AddOpt(&CppOptList, "-D", "__DICE_INLINE");
  678.                 }
  679.             }
  680.             break;
  681.             default:
  682.             eprintf("DCC: bad -m model\n");
  683.             uexit(20);
  684.             }
  685.             break;
  686.         case 'R':
  687. #ifdef COMMERCIAL
  688. #ifndef unix
  689.             /* substitution variables */
  690.  
  691.             if (*ptr >= '0' && *ptr <= '9')
  692.             RexxReplace[*ptr - '0'] = (ptr[1]) ? ptr + 1 : av[++i];
  693.  
  694.             /* rexx system up?    */
  695.  
  696.             if (RexxSysBase) {
  697.             RexxOpt = 1;
  698.             if (ErrFile == NULL) {
  699.                 char *ptr = TmpFileName(".e");
  700.  
  701.                 if ((ErrorFi = fopen(ptr, "a")) != NULL) {
  702.                 ErrFile = ptr;
  703.                 ErrFileIsTmp = 1;
  704.                 sprintf(ErrOptStr," -EE %s", ptr);
  705.                 } else {
  706.                 printf("unable to append to %s\n", ptr);
  707.                 }
  708.             }
  709.             } else {
  710.             eprintf("DCC: Warning: could open rexxsyslib.library!\n");
  711.             }
  712. #endif
  713. #endif
  714.             break;
  715.         case 's':
  716.             if (strcmp(ptr, "as") == 0) {
  717.             CompilerOpt = LATTICE_C;
  718.             } else if (strcmp(ptr, "ym") == 0) {
  719.                 dasAddSym = 1;
  720.             } else if (*ptr == '0') {
  721.             SymOpt = 0;
  722.             DebugOpts[0] = 0;
  723.             } else {
  724.             SymOpt = 1;
  725.             }
  726.             break;
  727.         case 'S':
  728.             if (*ptr == '0')
  729.             AltSectOpt = 0;
  730.             else
  731.             AltSectOpt = 1;
  732.             break;
  733.         case 'v':
  734.             if (*ptr == '0')
  735.             Verbose = 0;
  736.             else
  737.             Verbose = 1;
  738.             break;
  739.         case '/':
  740.             if (*ptr == '/') {
  741.             if (ptr[1] == '0')
  742.                 SlashSlashOpt = 0;
  743.             else
  744.                 SlashSlashOpt = 1;
  745.             break;
  746.             }
  747.             goto def;
  748.         case 'n':
  749.             if (strcmp(ptr, "ew") == 0) {
  750.             NewOpt = 1;
  751.             break;
  752.             }
  753.             if (strcmp(ptr, "ew0") == 0) {
  754.             NewOpt = 0;
  755.             break;
  756.             }
  757.             if (strcmp(ptr, "oheir") == 0) {
  758.             NoHeirOpt = 1;
  759.             break;
  760.             }
  761.             if (strcmp(ptr, "orom") == 0) {
  762.             RomOpt = 0;
  763.             break;
  764.             }
  765.             if (strcmp(ptr, "oproto") == 0) {
  766.             ProtoOnlyOpt = 0;
  767.             break;
  768.             }
  769.             if (strcmp(ptr, "o-env") == 0)
  770.             break;
  771.             if (strcmp(ptr, "o-ctl") == 0)
  772.             break;
  773.             /* fall through */
  774.         default:
  775.         def:
  776.             eprintf("DCC: bad - option\n");
  777.             help(1);
  778.         }
  779.         continue;
  780.         }
  781.         if (*ptr == '+') {
  782.         ptr += 2;
  783.  
  784.         switch(ptr[-1]) {
  785.         case 'I':   /*  +Idir   */
  786.             if (*ptr == 0)
  787.             ptr = av[++i];
  788.             AddOpt(&CppOptList, "+I", ptr);
  789.             break;
  790.         default:
  791.             eprintf("DCC: bad + option\n");
  792.             help(1);
  793.         }
  794.         continue;
  795.         }
  796.         if (*ptr == '@') {
  797.         FILE *fi = fopen(ptr + 1, "r");
  798.         char buf[128];
  799.  
  800.         if (fi == NULL) {
  801.             printf("unable to open %s\n", ptr + 1);
  802.             uexit(10);
  803.         }
  804.         while (fgets(buf, sizeof(buf), fi)) {
  805.             short len = strlen(buf);
  806.             if (len > 0)
  807.             buf[len-1] = 0;
  808.             if (buf[0] && buf[0] != ';' && buf[0] != '#') {
  809.             ++fc;
  810.             AddFile(buf);
  811.             }
  812.         }
  813.         fclose(fi);
  814.         continue;
  815.         }
  816.         ++fc;
  817.         AddFile(PathConvert(ptr));
  818.     }
  819.     if (i > ac) {
  820.         eprintf("DCC: file argument missing\n");
  821.         help(1);
  822.     }
  823.     }
  824.  
  825. #ifdef AZLAT_COMPAT
  826.     if (CompilerOpt == AZTEC_C) {
  827.     puts("DCC in AZTEC mode");
  828.     FastOpt = 0;
  829.     NoIntermediateAssembly = 1;
  830.     }
  831.     if (CompilerOpt == LATTICE_C) {
  832.     puts("DCC in LATTICE mode");
  833.     FastOpt = 0;
  834.     NoIntermediateAssembly = 1;
  835.     }
  836. #else
  837.     if (CompilerOpt != DICE_C)
  838.     puts("DCC must be recompiled w/ AZLAT_COMPAT defined");
  839. #endif
  840.  
  841.     /*
  842.      *    Ensure CLibApp and ALibApp ordering and remove duplicates
  843.      */
  844.  
  845.     OrderApp(CLibApp);
  846.     OrderApp(ALibApp);
  847.  
  848.     /*
  849.      *    If this run is to generate an executable,
  850.      *
  851.      *    (a) determine the name of the executable and
  852.      *    (b) delete it before compiling anything
  853.      */
  854.  
  855.     if (NoLink == 0) {
  856.     DefaultOutName();    /*  default output name     */
  857.     remove(OutFile);    /*  make sure it's deleted  */
  858.     }
  859.  
  860.     /*
  861.      *    Compile sources into assembly
  862.      *    Assemble assembly into objects
  863.      *    Link objects into executable
  864.      */
  865.  
  866.     {
  867.     NameNode *nn;
  868.  
  869.     for (nn = GetHead(&FList); nn; nn = GetSucc(&nn->n_Node)) {
  870.         if (IsMask(nn->n_IsType) == IS_CFILE) {
  871.         HandleCFile(nn, fc);
  872.         }
  873.         if (NoAsm == 0 && IsMask(nn->n_IsType) == IS_AFILE) {
  874.         HandleAFile(nn, fc);
  875.         }
  876.     }
  877.     }
  878.  
  879.     /*
  880.      *    Link objects into executable
  881.      */
  882.  
  883.     if (NoLink == 0) {
  884.     char *lfile;
  885.  
  886.     lfile = DoPrelink();
  887.     if (lfile)
  888.         PushTmpFile(lfile);
  889.     DoLink(lfile);
  890.     if (lfile) {
  891.         PopTmpFile(lfile);
  892.         remove(lfile);
  893.         free(lfile);
  894.     }
  895.     }
  896.     uexit(ExitCode);
  897.     return(0); /* not reached */
  898. }
  899.  
  900. void
  901. AddFile(ptr)
  902. char *ptr;
  903. {
  904.     char *t = Tailer(ptr);
  905.  
  906.     if (strncmp(t, "a", 1) == 0) {
  907.     AddName(&FList, NULL, ptr, IS_AFILE);
  908.     } else
  909.     if (strncmp(t, "o", 1) == 0) {
  910.     AddName(&FList, NULL, ptr, IS_OFILE);
  911.     } else
  912.     if (strncmp(t, "l", 1) == 0) {
  913.     AddName(&FList, NULL, ptr, IS_OFILE);
  914.     } else {
  915.     AddName(&FList, NULL, ptr, IS_CFILE);
  916.     }
  917. }
  918.  
  919. int
  920. DoCompile_Dice(in, out)
  921. char *in;
  922. char *out;
  923. {
  924.     char *qq = "";
  925.     char *cptmp = TmpFileName(".i");
  926.     char *code = (SmallCode) ? " -mc" : " -mC";
  927.     char *data = (SmallData) ? " -md" : " -mD";
  928.     char *rc = qq;
  929.     char *absdata;
  930.     char *concode;
  931.     char *res  = (ResOpt) ? " -r" : qq;
  932.     char *verb = (Verbose) ? " -v" : qq;
  933.     char *optsect = (AltSectOpt) ? " -S" : qq;
  934.     char *protoonly = (ProtoOnlyOpt) ? " -proto" : qq;
  935.     char *prof = (ProfOpt) ? " -prof" : qq;
  936.     char *mc68020 = (MC68020Opt) ? " -020" : qq;
  937.     char *mc68881 = (MC68881Opt) ? " -881" : qq;
  938.     char *piopt;
  939.     char *ffp = (FFPOpt) ? " -ffp" : qq;
  940.     char *genstack = (GenStackOpt) ? " -gs" : qq;
  941.     char *genlink  = (GenLinkOpt) ? " -gl" : qq;
  942.     char *slashopt = (SlashSlashOpt) ? " -//" : qq;
  943.     char *forkopt = (ForkOpt) ? " -fork" : qq;
  944.     char *unixcomopt = (UnixCommonOpt) ? " -mu" : qq;
  945.     char *asmopt = (NoAsm) ? " -a" : qq;
  946.     char *intopt = (IntOpt[0]) ? " -int" : qq;
  947.  
  948.     switch(RegCallOpt) {
  949.     case 1:
  950.     rc = " -mr";
  951.     break;
  952.     case 2:
  953.     rc = " -mR";
  954.     break;
  955.     case 3:
  956.     rc = " -mRR";
  957.     break;
  958.     case 4:
  959.     rc = " -mRRX";
  960.     break;
  961.     case 5:
  962.     rc = " -mRRY";
  963.     break;
  964.     }
  965.  
  966.     switch(ConstCode) {
  967.     case 1:
  968.     concode = " -ms";
  969.     break;
  970.     case 2:
  971.     concode = " -mS";
  972.     break;
  973.     default:
  974.     concode = qq;
  975.     break;
  976.     }
  977.  
  978.     switch(AbsData) {
  979.     case 1:
  980.     absdata = " -mw";
  981.     break;
  982.     case 2:
  983.     absdata = " -ma";
  984.     break;
  985.     default:
  986.     absdata = qq;
  987.     break;
  988.     }
  989.  
  990.     if (PIOpt) {
  991.     if (ResOpt)
  992.         piopt = " -pr";
  993.     else
  994.         piopt = " -pi";
  995.     res = qq;
  996.     absdata = qq;
  997.     code = qq;
  998.     data = qq;
  999.     } else {
  1000.     piopt = qq;
  1001.     }
  1002.  
  1003.     PushTmpFile(cptmp);
  1004.     sprintf(Buf, "%s %s -o %s%s%s%s%s",
  1005.     DCPP, in, cptmp, ErrOptStr, OptListToStr(&CppOptList),
  1006.     ffp, slashopt
  1007.     );
  1008.     run_cmd(in, Buf);
  1009.     sprintf(Buf, "%s %s -o %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
  1010.     DC1, cptmp, out, code, data, rc, res, verb,
  1011.     optsect, protoonly, prof, concode, absdata, piopt, ErrOptStr,
  1012.     mc68020, mc68881, ffp, genstack, genlink, forkopt, unixcomopt,
  1013.     asmopt, intopt, IntOpt,
  1014.     DebugOpts
  1015.     );
  1016.     run_cmd(in, Buf);
  1017.     PopTmpFile(cptmp);
  1018.     remove(cptmp);
  1019.     free(cptmp);
  1020.     return(0);
  1021. }
  1022.  
  1023. int
  1024. DoAssemble_Dice(cpath, in, out)
  1025. char *cpath;
  1026. char *in;
  1027. char *out;
  1028. {
  1029.     short n;
  1030.  
  1031.     n = sprintf(Buf, "%s %s-o%s %s%s", DAS, (dasAddSym ? "-s ":""), out, in, ErrOptStr);
  1032.     if (cpath)
  1033.     sprintf(Buf+n, " -N%s", cpath);
  1034.     run_cmd(cpath, Buf);
  1035.     return(0);
  1036. }
  1037.  
  1038. char *
  1039. DoPrelink_Dice(void)
  1040. {
  1041.     NameNode *nn;
  1042.     char *ltmp = TmpFileName(".lnk");
  1043.     FILE *fi = fopen(ltmp, "w");
  1044.  
  1045.     if (fi == NULL) {
  1046.     eprintf("DCC: couldn't create %s\n", ltmp);
  1047.     uexit(20);
  1048.     }
  1049.  
  1050.     for (nn = GetHead(&FList); nn; nn = GetSucc(&nn->n_Node)) {
  1051.     if (IsMask(nn->n_IsType) == IS_OFILE) {
  1052.         fputs(nn->n_In, fi);
  1053.         putc('\n', fi);
  1054.     }
  1055.     }
  1056.     while ((nn = (NameNode *)RemHead(&LList)) != NULL) {
  1057.     fputs(nn->n_In, fi);
  1058.     putc('\n', fi);
  1059.     }
  1060.  
  1061.     /*
  1062.      *    only small-data version of auto.lib is supported currently
  1063.      */
  1064.  
  1065.     if (RomOpt == 0 && NoDefaultLibs == 0) {
  1066.     fprintf(fi, "%s%s.lib", CLib, CLibApp);
  1067.     fprintf(fi, " %s%s%s.lib %sauto%s.lib\n",
  1068.         AmigaLib, ALibOS, ALibApp, DLib, (SmallData ? "s" : "l")
  1069.     );
  1070.     }
  1071.     fclose(fi);
  1072.     return(ltmp);
  1073. }
  1074.  
  1075. /*
  1076.  *  dlib:x.o is a special trailer for any autoinit code (in section autoinit,
  1077.  *  code)
  1078.  *
  1079.  *  This section is called in sequence just before main() with ac, av pushed on
  1080.  *  the stack.    The idea is that any module may reference an autoinit section to
  1081.  *  automatically initialize certain aspects of itself without requiring a call
  1082.  *  from the main program.
  1083.  */
  1084.  
  1085. int
  1086. DoLink_Dice(lfile)
  1087. char *lfile;
  1088. {
  1089.     char *qq = "";
  1090.     char *co = " ";
  1091.     char *ro = mergestr(DLib, "x.o");
  1092.     char *symopt = (SymOpt) ? " -s" : qq;
  1093.     char *resopt = (ResOpt) ? " -r" : qq;
  1094.     char *fragopt= (FragOpt) ? " -frag" : qq;
  1095.     char *chipopt= (ChipOpt) ? " -chip" : qq;
  1096.     char *postfix= qq;
  1097.     char *piopt;
  1098.     char absdata[20];
  1099.     char *verb = (Verbose) ? " -v" : qq;
  1100.  
  1101.     if (DLinkPostFixOpt) {
  1102.     static char PostFix[sizeof(CLibApp)+3];
  1103.     postfix = PostFix;
  1104.     sprintf(postfix, " -P%s", CLibApp);
  1105.     }
  1106.  
  1107.     if (RomOpt == 0 && NoDefaultLibs == 0) {
  1108.     co = SCode[(short)((PIOpt << 1) | ResOpt)];
  1109.     }
  1110.  
  1111.     if (AbsData) {
  1112.     sprintf(absdata, " -ma 0x%lx", AbsDataStart);
  1113.     } else {
  1114.     absdata[0] = 0;
  1115.     }
  1116.  
  1117.     if (PIOpt) {
  1118.     if (ResOpt)
  1119.         piopt = " -pr";
  1120.     else
  1121.         piopt = " -pi";
  1122.     resopt = qq;
  1123.     if (AbsData) {
  1124.         absdata[0] = 0;
  1125.         puts("Warning: cannot mix -pi and -ma/-mw");
  1126.     }
  1127.     } else {
  1128.     piopt = qq;
  1129.     }
  1130.     if (FragOpt) {
  1131.     if (ResOpt) {
  1132.         puts("Warning: cannot use -frag with -r");
  1133.         fragopt = qq;
  1134.     }
  1135.     }
  1136.  
  1137.     sprintf(Buf, "%s %s @%s %s -o %s%s%s%s%s%s%s%s%s%s%s%s",
  1138.     DLINK, co, lfile, ro, OutFile,
  1139.     symopt,
  1140.     resopt,
  1141.     fragopt,
  1142.     piopt,
  1143.     absdata,
  1144.     postfix,
  1145.     chipopt,
  1146.     OptListToStr(&LinkOptList),
  1147.     ErrOptStr,
  1148.     DebugOpts,
  1149.     verb
  1150.     );
  1151.     run_cmd("", Buf);
  1152.     free(ro);
  1153.  
  1154.     /*
  1155.      * Delete temporary objects
  1156.      */
  1157.  
  1158.     {
  1159.     NameNode *nn;
  1160.  
  1161.         for (nn = GetHead(&FList); nn; nn = GetSucc(&nn->n_Node)) {
  1162.         if (nn->n_IsType & IS_TMP)
  1163.         remove(nn->n_In);
  1164.     }
  1165.     }
  1166.     return(0);
  1167. }
  1168.  
  1169. void
  1170. help(int code)
  1171. {
  1172.     printf("%s\n%s\n", VSTRING, DCopyright);
  1173.     uexit(code);
  1174. }
  1175.  
  1176. char *
  1177. TmpFileName(tail)
  1178. char *tail;
  1179. {
  1180.     char *buf = malloc(strlen(TmpDir) + strlen(tail) + 32);
  1181.     char dummy = 0;
  1182.  
  1183.     sprintf(buf, "%s%06lx%s", TmpDir, (long)&dummy >> 8, tail);
  1184.     return(buf);
  1185. }
  1186.  
  1187. /*
  1188.  *  file    -    file to modify
  1189.  *  hdr     -    new directory path to put file
  1190.  *  tail    -    new suffix
  1191.  *
  1192.  */
  1193.  
  1194. char *
  1195. MungeFile(file, hdr, tail)
  1196. char *file;
  1197. char *hdr;
  1198. char *tail;
  1199. {
  1200.     char *name = malloc(strlen(file) + (hdr ? strlen(hdr) : 0) + (tail ? strlen(tail) : 0) + 2);
  1201.     char *ptr;
  1202.     short n = 0;
  1203.  
  1204.     /*
  1205.      *    Prepend header, replacing the absolute portion of the file
  1206.      */
  1207.  
  1208.     if (hdr) {
  1209.     if ((ptr = strchr(file, ':')) != NULL)
  1210.         file = ptr + 1;
  1211.     n += sprintf(name + n, "%s", hdr);
  1212.  
  1213.     if (n && name[n-1] != ':' && name[n-1] != '/')
  1214.         name[n++] = '/';
  1215.     }
  1216.  
  1217.     /*
  1218.      *    The file
  1219.      */
  1220.  
  1221.     if (tail && (ptr = strrchr(file, '.'))) {
  1222.     n += sprintf(name + n, "%.*s", ptr - file, file);
  1223.     } else {
  1224.     n += sprintf(name + n, "%s", file);
  1225.     }
  1226.  
  1227.     /*
  1228.      *    Trailer
  1229.      */
  1230.  
  1231.     if (tail) {
  1232.     n += sprintf(name + n, "%s", tail);
  1233.     }
  1234.     name[n] = 0;
  1235.     return(name);
  1236. }
  1237.  
  1238. void
  1239. AddName(List *list, char *tailifnone, char *file, short isType)
  1240. {
  1241.     NameNode *nn = malloc(sizeof(NameNode));
  1242.     short i;
  1243.  
  1244.     for (i = strlen(file) - 1; i >= 0 && file[i] != '.'; --i) {
  1245.     if (file[i] == '/' || file[i] == ':')
  1246.         i = 0;
  1247.     }
  1248.  
  1249.     if (i < 0 && tailifnone) {
  1250.     nn->n_In = malloc(strlen(file) + strlen(tailifnone) + 1);
  1251.     sprintf(nn->n_In, "%s%s", file, tailifnone);
  1252.     } else {
  1253.     nn->n_In = malloc(strlen(file) + 1);
  1254.     strcpy(nn->n_In, file);
  1255.     }
  1256.     nn->n_Out = NULL;
  1257.     nn->n_IsType= isType;
  1258.     AddTail(list, &nn->n_Node);
  1259. }
  1260.  
  1261. NameNode *
  1262. AddOpt(list, opt, body)
  1263. List *list;
  1264. char *opt;
  1265. char *body;
  1266. {
  1267.     NameNode *nn = malloc(sizeof(NameNode));
  1268.  
  1269.     nn->n_In = opt;
  1270.     nn->n_Out= body;
  1271.     AddTail(list, &nn->n_Node);
  1272.     return(nn);
  1273. }
  1274.  
  1275. char *
  1276. Tailer(ptr)
  1277. char *ptr;
  1278. {
  1279.     short i;
  1280.  
  1281.     for (i = strlen(ptr) - 1; i >= 0 && ptr[i] != '.'; --i);
  1282.     if (i < 0)
  1283.     return("");
  1284.     return(ptr + i + 1);
  1285. }
  1286.  
  1287. char *
  1288. XFilePart(ptr)
  1289. char *ptr;
  1290. {
  1291.     short i;
  1292.  
  1293.     for (i = strlen(ptr) - 1; i >= 0 && ptr[i] != ':' && ptr[i] != '/'; --i);
  1294.     ++i;
  1295.     return(ptr + i);
  1296. }
  1297.  
  1298. char *
  1299. OptListToStr(list)
  1300. List *list;
  1301. {
  1302.     static char Tmp[512];
  1303.     short i;
  1304.     NameNode *scan;
  1305.  
  1306.     i = 0;
  1307.     Tmp[0] = 0;
  1308.     for (scan = (NameNode *)list->lh_Head; scan != (NameNode *)&list->lh_Tail; scan = (NameNode *)scan->n_Node.ln_Succ) {
  1309.     sprintf(Tmp + i, " %s%s", scan->n_In, scan->n_Out);
  1310.     i += strlen(Tmp + i);
  1311.     }
  1312.     return(Tmp);
  1313. }
  1314.  
  1315. #ifdef AZLAT_COMPAT
  1316.  
  1317. char *
  1318. OptListToStr2(list, cvt)
  1319. List *list;
  1320. char *cvt;
  1321. {
  1322.     static char Tmp[512];
  1323.     short i;
  1324.     NameNode *scan;
  1325.  
  1326.     i = 0;
  1327.     for (scan = (NameNode *)list->lh_Head; scan != (NameNode *)&list->lh_Tail; scan = (NameNode *)scan->n_Node.ln_Succ) {
  1328.     sprintf(Tmp + i, " %s%s", scan->n_In, scan->n_Out);
  1329.     {
  1330.         char *ptr;
  1331.         for (ptr = cvt; *ptr; ptr += 2) {
  1332.         if (Tmp[i+2] == ptr[0])
  1333.             Tmp[i+2] = ptr[1];
  1334.         }
  1335.     }
  1336.     i += strlen(Tmp + i);
  1337.     }
  1338.     return(Tmp);
  1339. }
  1340.  
  1341. #endif
  1342.  
  1343. /*
  1344.  *  run_cmd(buf)    buf[-1] is valid for BCPL stuff, buf[-1] is
  1345.  *            long word aligned.
  1346.  */
  1347.  
  1348. #ifdef AMIGA
  1349.  
  1350. void
  1351. run_cmd(cfile, buf)
  1352. char *cfile;        /* REXX support */
  1353. char *buf;
  1354. {
  1355.     short i;
  1356.     short j = strlen(buf);
  1357.     int r;
  1358.  
  1359.     if (ErrFile && ErrorFi) {
  1360.     fclose(ErrorFi);
  1361.     ErrorFi = NULL;
  1362.     }
  1363.  
  1364.     /*
  1365.      *    top (hack to support REXX fix/continue)
  1366.      */
  1367.  
  1368. top:
  1369.     if (Verbose)
  1370.     printf("%s\n", buf);
  1371.  
  1372.  
  1373. #if INCLUDE_VERSION >= 36
  1374.     if (SysBase->lib_Version >= 36) {
  1375.     long seg;
  1376.     long lock = NULL;
  1377.  
  1378.     Process *proc = (Process *)FindTask(NULL);
  1379.     CLI *cli = BTOC(proc->pr_CLI, CLI);
  1380.     long oldCommandName;
  1381.  
  1382.     dbprintf(("cmd-begin\n"));
  1383.  
  1384.     for (i = 0; buf[i] && buf[i] != ' '; ++i)
  1385.         ;
  1386.     movmem(buf, CmdName + 1, i);
  1387.     CmdName[0] = i;
  1388.     CmdName[i+1] = 0;
  1389.  
  1390.     if (cli) {
  1391.         oldCommandName = (long)cli->cli_CommandName;
  1392.         cli->cli_CommandName = CTOB(CmdName);
  1393.     }
  1394.  
  1395.     if (seg = (long)FindSegment(CmdName + 1, 0L, 0)) {
  1396.         r = RunCommand(((long *)seg)[2], 16384, buf + i + 1, strlen(buf + i + 1));
  1397.     } else if ((lock = _SearchPath(CmdName + 1)) && (seg = LoadSegLock(lock, ""))) {
  1398.         r = RunCommand(seg, 16384, buf + i + 1, strlen(buf + i + 1));
  1399.         UnLoadSeg(seg);
  1400.     } else if ((lock = Lock("dcc:bin", SHARED_LOCK)) && (seg = LoadSegLock(lock, CmdName + 1))) {
  1401.         r = RunCommand(seg, 16384, buf + i + 1, strlen(buf + i + 1));
  1402.         UnLoadSeg(seg);
  1403.     } else {
  1404.         printf("Unable to find executable %s resident, via your path\n", CmdName + 1);
  1405.         printf("or in DCC:BIN!\n");
  1406.         r = 20;
  1407.     }
  1408.     if (lock)
  1409.         UnLock(lock);
  1410.     if (cli)
  1411.         cli->cli_CommandName = (BSTR)oldCommandName;
  1412.  
  1413.     dbprintf(("cmd-end\n"));
  1414.     } else {
  1415. #else
  1416.     {
  1417. #endif
  1418.  
  1419. #ifdef _DCC
  1420.     if (FastOpt == 0) {
  1421. #endif
  1422.         if (Execute(buf, NULL, Output()) != -1) {
  1423.         printf("Unable to Execute %s\n", buf);
  1424.         uexit(20);
  1425.         }
  1426.         r = 0;
  1427.  
  1428. #ifdef _DCC
  1429.     } else {
  1430.         for (i = 0; buf[i] && buf[i] != ' '; ++i)
  1431.         ;
  1432.         buf[i] = 0;
  1433.         if (i != j) {
  1434.         for (++i; buf[i] == ' '; ++i)
  1435.             ;
  1436.         }
  1437.         r = exec_dcc(buf, buf + i);
  1438.     }
  1439. #endif
  1440.     }
  1441.     if (r)
  1442.     printf("Exit code %d\n", r);
  1443. #ifdef COMMERCIAL
  1444. #ifndef unix
  1445.     if (RexxOpt)
  1446.     {
  1447.     if (r)
  1448.     {
  1449.         long rr = HandleErrorRexx(cfile, buf, r);
  1450.         if (rr == 2)
  1451.         goto top;
  1452.     } else {
  1453.         FlushStoredErrors(cfile);
  1454.     }
  1455.     }
  1456. #endif
  1457. #endif
  1458.     if (ExitCode < r)
  1459.     ExitCode = r;
  1460.     if (ExitCode > 5)
  1461.     uexit(ExitCode);
  1462.  
  1463.     /*
  1464.      *    close and reopen file to 'sync' it
  1465.      */
  1466.  
  1467.     if (r && ErrFile) {
  1468.     ErrorFi = fopen(ErrFile, "a");
  1469.     }
  1470. }
  1471.  
  1472. #else
  1473.  
  1474. #include <sys/wait.h>
  1475.  
  1476. void
  1477. run_cmd(cfile, buf)
  1478. char *cfile;        /* REXX support */
  1479. char *buf;
  1480. {
  1481.     int r;
  1482.  
  1483.     if (Verbose)
  1484.     printf("%s\n", buf);
  1485.  
  1486.     if ((r = vfork()) == 0) {
  1487.     execlp("/bin/sh", "/bin/sh", "-c", buf, 0);
  1488.     uexit(30);
  1489.     } else {
  1490. #ifdef linux
  1491.     union wait uwait;
  1492.     while (wait(&uwait) != r || WIFEXITED(uwait) == 0)
  1493.         ;
  1494.     r = uwait.w_retcode;
  1495. #else
  1496.     int status;
  1497.     while (wait(&status) != r || WIFEXITED(status) == 0)
  1498.         ;
  1499.     r = WEXITSTATUS(status);
  1500. #endif
  1501.     }
  1502.  
  1503.     if (r)
  1504.     printf("Exit code %d\n", r);
  1505.     if (ExitCode < r)
  1506.     ExitCode = r;
  1507.     if (ExitCode > 5)
  1508.     uexit(ExitCode);
  1509. }
  1510.  
  1511. #endif
  1512.  
  1513. #ifdef AMIGA
  1514.  
  1515. int
  1516. OutOfDate(in, out)
  1517. char *in;
  1518. char *out;
  1519. {
  1520.     static FIB *InFib;
  1521.     static FIB *OutFib;
  1522.     BPTR inLock, outLock;
  1523.     FIB *inFib;
  1524.     FIB *outFib;
  1525.     int r = 1;
  1526.  
  1527.     if (NewOpt == 0)
  1528.     return(1);
  1529.  
  1530.     if (InFib == NULL) {
  1531.     InFib = malloc(sizeof(FIB));
  1532.     OutFib = malloc(sizeof(FIB));
  1533.     }
  1534.     inFib = InFib;
  1535.     outFib = OutFib;
  1536.  
  1537.     if (inLock = Lock(in, SHARED_LOCK)) {
  1538.     if (outLock = Lock(out, SHARED_LOCK)) {
  1539.         if (Examine(inLock, inFib) && Examine(outLock, outFib)) {
  1540.         if (inFib->fib_Date.ds_Days < outFib->fib_Date.ds_Days)
  1541.             r = 0;
  1542.         else if (inFib->fib_Date.ds_Days == outFib->fib_Date.ds_Days) {
  1543.             if (inFib->fib_Date.ds_Minute < outFib->fib_Date.ds_Minute)
  1544.             r = 0;
  1545.             else if (inFib->fib_Date.ds_Minute == outFib->fib_Date.ds_Minute) {
  1546.             if (inFib->fib_Date.ds_Tick < outFib->fib_Date.ds_Tick)
  1547.                 r = 0;
  1548.             }
  1549.         }
  1550.         }
  1551.         UnLock(outLock);
  1552.     }
  1553.     UnLock(inLock);
  1554.     }
  1555.     return(r);
  1556. }
  1557.  
  1558. #else
  1559.  
  1560. int
  1561. OutOfDate(in, out)
  1562. char *in;
  1563. char *out;
  1564. {
  1565.     struct stat instat;
  1566.     struct stat outstat;
  1567.     int r = 1;
  1568.  
  1569.     if (NewOpt == 0)
  1570.     return(1);
  1571.  
  1572.     if (stat(in, &instat) == 0) {
  1573.     if (stat(out, &outstat) == 0) {
  1574.         if (instat.st_mtime < outstat.st_mtime)
  1575.         r = 0;
  1576.     }
  1577.     }
  1578.     return(r);
  1579. }
  1580.  
  1581. #endif
  1582.  
  1583. void
  1584. HandleCFile(nn, fc)
  1585. NameNode *nn;
  1586. int fc;
  1587. {
  1588.     char *asmName;
  1589.     char *objName;
  1590.  
  1591.     if (fc == 1 && OutFile && NoAsm)
  1592.     asmName = OutFile;
  1593.     else if (NoAsm)
  1594.     asmName = MungeFile(nn->n_In, OutDir, ".a");
  1595.     else
  1596.     asmName = MungeFile(XFilePart(nn->n_In), TmpDir, ".a");
  1597.  
  1598.     nn->n_IsType = IS_OFILE;
  1599.  
  1600.     if (fc == 1 && OutFile && NoLink) {
  1601.     objName = OutFile;
  1602.     } else if (NoLink) {
  1603.     objName = MungeFile(nn->n_In, OutDir, ".o");
  1604.     } else {
  1605.     objName = MungeFile(XFilePart(nn->n_In), TmpDir, ".o");
  1606.     nn->n_IsType |= IS_TMP;
  1607.     }
  1608.  
  1609.     if (NoAsm) {    /*  in -> asmName        */
  1610.     if (OutOfDate(nn->n_In, asmName))
  1611.         DoCompile(nn->n_In, asmName);
  1612.     } else {        /*  in -> asmName -> objName*/
  1613.     if (OutOfDate(nn->n_In, objName)) {
  1614.         PushTmpFile(asmName);
  1615.         if (NoIntermediateAssembly) {
  1616.         DoCompile(nn->n_In, objName);
  1617.         } else {
  1618.         DoCompile(nn->n_In, asmName);
  1619.         if (NoHeirOpt == 0)
  1620.             CreateObjPath(objName);
  1621.         DoAssemble(nn->n_In, asmName, objName);
  1622.         }
  1623.         PopTmpFile(asmName);
  1624.         remove(asmName);
  1625.     }
  1626.     }
  1627.     nn->n_In = strdup(objName);
  1628. }
  1629.  
  1630. void
  1631. HandleAFile(nn, fc)
  1632. NameNode *nn;
  1633. int fc;
  1634. {
  1635.     char *objName;
  1636.  
  1637.     nn->n_IsType = IS_OFILE;
  1638.  
  1639.     if (fc == 1 && OutFile && NoLink) {
  1640.     objName = OutFile;
  1641.     } else if (NoLink) {
  1642.     objName = MungeFile(nn->n_In, OutDir, ".o");
  1643.     } else {
  1644.     objName = MungeFile(XFilePart(nn->n_In), TmpDir, ".o");
  1645.     nn->n_IsType |= IS_TMP;
  1646.     }
  1647.  
  1648.     if (OutOfDate(nn->n_In, objName)) {
  1649.     if (NoHeirOpt == 0)
  1650.         CreateObjPath(objName);
  1651.     DoAssemble(NULL, nn->n_In, objName);
  1652.     }
  1653.     nn->n_In = strdup(objName);
  1654. }
  1655.  
  1656. void
  1657. PushTmpFile(name)
  1658. char *name;
  1659. {
  1660.     Node *node = malloc(sizeof(Node) + strlen(name) + 1);
  1661.     if (node == NULL) {
  1662.     puts("Ran out of memory!");
  1663.     uexit(25);
  1664.     }
  1665.     node->ln_Name = (char *)(node + 1);
  1666.     strcpy(node->ln_Name, name);
  1667.     AddHead(&TmpList, node);
  1668. }
  1669.  
  1670. void
  1671. PopTmpFile(name)
  1672. char *name;
  1673. {
  1674.     Node *node = RemHead(&TmpList);
  1675.  
  1676.     if (node == NULL || strcmp(name, node->ln_Name) != 0) {
  1677.     puts("PopTmpFile: software error");
  1678.     uexit(20);
  1679.     }
  1680.     free(node);
  1681. }
  1682.  
  1683. #ifdef AMIGA
  1684.  
  1685. long
  1686. LoadSegLock(lock, cmd)
  1687. long lock;
  1688. char *cmd;
  1689. {
  1690.     long oldLock;
  1691.     long seg;
  1692.  
  1693.     oldLock = CurrentDir(lock);
  1694.     seg = LoadSeg(cmd);
  1695.     CurrentDir(oldLock);
  1696.     return(seg);
  1697. }
  1698.  
  1699. #endif
  1700.  
  1701. void
  1702. DefaultOutName(void)
  1703. {
  1704.     NameNode *nn;
  1705.  
  1706.     /*
  1707.      *    if no output file name set and only one source file was specified,
  1708.      *    set output file name based on said file
  1709.      */
  1710.  
  1711.     if (OutFile == NULL) {
  1712.     OutFile = "a.out";
  1713.  
  1714.     if ((nn = GetHead(&FList)) != NULL) {
  1715.         /*if (GetSucc(&nn->n_Node) == NULL)*/ {
  1716.         char *ptr = strdup(nn->n_In);
  1717.         char *p0;
  1718.  
  1719.         if ((p0 = strrchr(ptr, '.')) != NULL) {
  1720.             *p0 = 0;
  1721.             OutFile = ptr;
  1722.         }
  1723.         }
  1724.     }
  1725.     }
  1726. }
  1727.  
  1728. /*
  1729.  *    AZTEC C, LATTICE C COMPATIBILITY OPTIONS
  1730.  */
  1731.  
  1732. #ifdef AZLAT_COMPAT
  1733.  
  1734. DoLink(lfile)
  1735. char *lfile;
  1736. {
  1737.     switch(CompilerOpt) {
  1738.     case DICE_C:
  1739.     return(DoLink_Dice(lfile));
  1740.     case LATTICE_C:
  1741.     return(DoLink_Lattice(lfile));
  1742.     case AZTEC_C:
  1743.     return(DoLink_Aztec(lfile));
  1744.     }
  1745. }
  1746.  
  1747. DoCompile(in, out)
  1748. char *in;
  1749. char *out;
  1750. {
  1751.     switch(CompilerOpt) {
  1752.     case DICE_C:
  1753.     return(DoCompile_Dice(in, out));
  1754.     case LATTICE_C:
  1755.     return(DoCompile_Lattice(in, out));
  1756.     case AZTEC_C:
  1757.     return(DoCompile_Aztec(in, out));
  1758.     }
  1759.     return(0);
  1760. }
  1761.  
  1762. DoAssemble(cfile, in, out)
  1763. char *cfile;
  1764. char *in;
  1765. char *out;
  1766. {
  1767.     switch(CompilerOpt) {
  1768.     case DICE_C:
  1769.     return(DoAssemble_Dice(cfile, in, out));
  1770.     case LATTICE_C:
  1771.     return(DoAssemble_Lattice(cfile, in, out));
  1772.     case AZTEC_C:
  1773.     return(DoAssemble_Aztec(cfile, in, out));
  1774.     }
  1775.     return(0);
  1776. }
  1777.  
  1778. char *
  1779. DoPrelink(void)
  1780. {
  1781.     switch(CompilerOpt) {
  1782.     case DICE_C:
  1783.     return(DoPrelink_Dice());
  1784.     case LATTICE_C:
  1785.     return(DoPrelink_Lattice());
  1786.     case AZTEC_C:
  1787.     return(DoPrelink_Aztec());
  1788.     }
  1789.     return(0);
  1790. }
  1791.  
  1792. /*
  1793.  *    ------------------------------------------------------------------
  1794.  */
  1795.  
  1796. DoCompile_Lattice(in, out)
  1797. char *in;
  1798. char *out;
  1799. {
  1800.     char *qq = "";
  1801.     char *cptmp = TmpFileName(".i");
  1802.     char *data = (SmallData) ? qq : " -b0";
  1803.  
  1804.     sprintf(Buf, "lc -o%s %s %s %s",
  1805.     out, OptListToStr2(&CppOptList, "DdIi"), data, in
  1806.     );
  1807.     run_cmd(in, Buf);
  1808.  
  1809.     free(cptmp);
  1810.     return(0);
  1811. }
  1812.  
  1813. DoAssemble_Lattice(cfile, in, out)
  1814. char *cfile;
  1815. char *in;
  1816. char *out;
  1817. {
  1818.     sprintf(Buf, "asm -o%s %s", out, in);
  1819.     run_cmd(cfile, Buf);
  1820.     return(0);
  1821. }
  1822.  
  1823. char *
  1824. DoPrelink_Lattice(void)
  1825. {
  1826.     NameNode *nn;
  1827.     char *ltmp = TmpFileName(".lnk");
  1828.     FILE *fi = fopen(ltmp, "w");
  1829.     short libs = 0;
  1830.  
  1831.     if (fi == NULL) {
  1832.     eprintf("DCC: couldn't create %s\n", ltmp);
  1833.     uexit(20);
  1834.     }
  1835.  
  1836.     for (nn = GetHead(&FList); nn; nn = GetSucc(&nn->n_Node)) {
  1837.     if (IsMask(nn->n_IsType) == IS_OFILE) {
  1838.         fputs(nn->n_In, fi);
  1839.         putc('\n', fi);
  1840.     }
  1841.     }
  1842.  
  1843.     while (nn = (NameNode *)RemHead(&LList)) {
  1844.     if (libs == 0) {
  1845.         fprintf(fi, "LIB ");
  1846.         libs = 1;
  1847.     }
  1848.     fputs(nn->n_In, fi);
  1849.     putc('\n', fi);
  1850.     }
  1851.     if (RomOpt == 0 && NoDefaultLibs == 0) {
  1852.     if (libs == 0) {
  1853.         fprintf(fi, "LIB ");
  1854.         libs = 1;
  1855.     }
  1856.     fprintf(fi, "lib:lc.lib lib:amiga.lib\n");
  1857.     }
  1858.  
  1859.     fclose(fi);
  1860.     return(ltmp);
  1861. }
  1862.  
  1863. DoLink_Lattice(lfile)
  1864. char *lfile;
  1865. {
  1866.     char *qq = "";
  1867.     char *co = " ";
  1868.     char *symopt = (SymOpt) ? " ADDSYM" : qq;
  1869.     char *scopt = (SmallData) ? " SD" : qq;
  1870.     char *sdopt = (SmallCode) ? " SC" : qq;
  1871.  
  1872.     if (RomOpt == 0 && NoDefaultLibs == 0) {       /*  RomOpt PIOpt ResOpt */
  1873.     static char *SCode[] = { "lib:c.o",         /*    0      0      0   */
  1874.                  "lib:cres.o",      /*    0      0      1   */
  1875.                  "lib:c.o",         /*    0      1      0   */
  1876.                  "lib:cres.o"       /*    0      1      1   */
  1877.                    };
  1878.     co = SCode[(short)((PIOpt << 1) | ResOpt)];
  1879.     }
  1880.  
  1881.     sprintf(Buf, "BLink from %s with %s to %s%s%s%s",
  1882.     co, lfile, OutFile, symopt, scopt, sdopt
  1883.     );
  1884.     run_cmd("", Buf);
  1885.     return(0);
  1886. }
  1887.  
  1888. /*
  1889.  *  ---------------------------------------------------------------------
  1890.  */
  1891.  
  1892. DoCompile_Aztec(in, out)
  1893. char *in;
  1894. char *out;
  1895. {
  1896.     char *qq = "";
  1897.     char *cptmp = TmpFileName(".i");
  1898.     char *data = (SmallData) ? qq : qq;
  1899.  
  1900.     sprintf(Buf, "cc %s %s %s -o %s",
  1901.     OptListToStr2(&CppOptList, ""), data, in, out
  1902.     );
  1903.     run_cmd(in, Buf);
  1904.  
  1905.     free(cptmp);
  1906.     return(0);
  1907. }
  1908.  
  1909. DoAssemble_Aztec(cfile, in, out)
  1910. char *cfile;
  1911. char *in;
  1912. char *out;
  1913. {
  1914.     sprintf(Buf, "as %s -o %s", in, out);
  1915.     run_cmd(cfile, Buf);
  1916.     return(0);
  1917. }
  1918.  
  1919. char *
  1920. DoPrelink_Aztec(void)
  1921. {
  1922.     NameNode *nn;
  1923.     char *ltmp = TmpFileName(".lnk");
  1924.     FILE *fi = fopen(ltmp, "w");
  1925.  
  1926.     if (fi == NULL) {
  1927.     eprintf("DCC: couldn't create %s\n", ltmp);
  1928.     uexit(20);
  1929.     }
  1930.  
  1931.     for (nn = GetHead(&FList); nn; nn = GetSucc(&nn->n_Node)) {
  1932.     if (IsMask(nn->n_IsType) == IS_OFILE) {
  1933.         fputs(nn->n_In, fi);
  1934.         putc('\n', fi);
  1935.     }
  1936.     }
  1937.     while (nn = (NameNode *)RemHead(&LList)) {
  1938.     fputs(nn->n_In, fi);
  1939.     putc('\n', fi);
  1940.     }
  1941.     if (RomOpt == 0 && NoDefaultLibs == 0) {
  1942.     fprintf(fi, "-lc\n");
  1943.     }
  1944.     fclose(fi);
  1945.     return(ltmp);
  1946. }
  1947.  
  1948. DoLink_Aztec(lfile)
  1949. char *lfile;
  1950. {
  1951.     char *qq = "";
  1952.  
  1953.     sprintf(Buf, "ln -f %s -o %s", lfile, OutFile);
  1954.     run_cmd("", Buf);
  1955.     return(0);
  1956. }
  1957.  
  1958. #endif
  1959.  
  1960. void
  1961. OrderApp(buf)
  1962. char *buf;
  1963. {
  1964.     short i;
  1965.     short c;
  1966.     char sort[26];
  1967.  
  1968.     setmem(sort, sizeof(sort), 0);
  1969.     for (i = 0; (c = buf[i]) != 0; ++i) {
  1970.     if (c >= 'a' && c <= 'z')
  1971.         sort[c-'a'] = 1;
  1972.     }
  1973.     for (i = sizeof(sort) - 1, c = 0; i >= 0; --i) {
  1974.     if (sort[i])
  1975.         buf[c++] = i + 'a';
  1976.     }
  1977.     buf[c] = 0;
  1978. }
  1979.  
  1980. void
  1981. AddLibApp(char *buf, char c)
  1982. {
  1983.     short i = strlen(buf);
  1984.  
  1985.     if (strchr(buf, c) == NULL) {
  1986.     buf[i+0] = c;
  1987.     buf[i+1] = 0;
  1988.     }
  1989. }
  1990.  
  1991. void
  1992. DelLibApp(char *buf, char c)
  1993. {
  1994.     char *ptr;
  1995.  
  1996.     if ((ptr = strchr(buf, c)) != NULL)
  1997.     movmem(ptr + 1, ptr, strlen(ptr + 1) + 1);
  1998. }
  1999.  
  2000. char *
  2001. PathConvert(path)
  2002. char *path;
  2003. {
  2004. #ifdef _DCC
  2005.     if (strstr(path, "./") || strstr(path, "../"))
  2006.     return(strdup(UnixToAmigaPath(path)));
  2007. #endif
  2008.     return(path);
  2009. }
  2010.  
  2011. void *
  2012. GetHead(list)
  2013. List *list;
  2014. {
  2015.     if (list->lh_Head != (Node *)&list->lh_Tail)
  2016.     return(list->lh_Head);
  2017.     return(NULL);
  2018. }
  2019.  
  2020. void *
  2021. GetSucc(node)
  2022. Node *node;
  2023. {
  2024.     Node *r = node->ln_Succ;
  2025.  
  2026.     if (r->ln_Succ)
  2027.     return(r);
  2028.     return(NULL);
  2029. }
  2030.  
  2031. char *
  2032. mergestr(const char *s1, const char *s2)
  2033. {
  2034.     char *ptr = malloc(strlen(s1) + strlen(s2) + 1);
  2035.     sprintf(ptr, "%s%s", s1, s2);
  2036.     return(ptr);
  2037. }
  2038.  
  2039.  
  2040. #ifdef COMMERCIAL
  2041. #ifndef unix
  2042.  
  2043. void
  2044. FlushStoredErrors(cfile)
  2045. char *cfile;
  2046. {
  2047.     char *fullPath;
  2048.     char *port = "DICE_ERROR_PARSER";
  2049.  
  2050.     if ( (cfile != NULL) &&
  2051.          (cfile[0])      &&
  2052.          (FindPort(port) != NULL) &&
  2053.          ((fullPath = FullPathOf(cfile)) != NULL))
  2054.     {
  2055.         char *cmd;
  2056.         char *curDirPath = FullPathOf("");
  2057.  
  2058.     cmd = ScanReplace("Load Nil: %n %c", fullPath, "nil:", curDirPath);
  2059.     if (cmd != NULL)
  2060.     {
  2061.         /* Note that we don't care if this fails for any reason, we  */
  2062.         /* just want to give them an opportunity to purge any errors */
  2063.         /* that have been stored                                     */
  2064.         PlaceRexxCommandDirect(NULL,port,cmd,NULL,NULL);
  2065.         free(cmd);
  2066.     }
  2067.     if (curDirPath != NULL) free(curDirPath);
  2068.     free(fullPath);
  2069.     }
  2070. }
  2071.  
  2072. /*
  2073.  *  HANDLEERRORREXX()
  2074.  *
  2075.  *  Scan DCC:CONFIG/DCC.CONFIG to obtain REXX command execution information
  2076.  *  then attempt to run the appropriate command.  If the REXX script returns
  2077.  *  2 we retry the compilation.  If the REXX script returns anything else
  2078.  *  we abort.
  2079.  *
  2080.  *  cfile can be "", indicating no source file available to handle error(s)
  2081.  */
  2082.  
  2083. int
  2084. HandleErrorRexx(cfile, cmdbuf, rc)
  2085. char *cfile;
  2086. char *cmdbuf;
  2087. int rc;
  2088. {
  2089.     FILE *fi;
  2090.     int r = -1;
  2091.     char *buf;
  2092.     char *fullPath;
  2093.     char *cmdName = "cmd=";
  2094.     char *portName = "port=";
  2095.     char *rexxCmdName = "rexxcmd=";
  2096.     char *curDirPath = FullPathOf("");
  2097.  
  2098.  
  2099.     if (buf = malloc(256)) {
  2100.     /*
  2101.      *  obtain full path to cFile, if present
  2102.      */
  2103.  
  2104.     if ((cfile != NULL) && cfile[0]) {
  2105.         fullPath = FullPathOf(cfile);
  2106.     } else {
  2107.         fullPath = strdup("");
  2108.         cmdName = "linkcmd=";
  2109.         portName = "linkport=";
  2110.         rexxCmdName = "linkrexxcmd=";
  2111.     }
  2112.     if (fullPath) {
  2113.         /*
  2114.          *    open the config file
  2115.          */
  2116.  
  2117.         if (fi = fopen("DCC:CONFIG/DCC.CONFIG", "r")) {
  2118.         char *cmd = NULL;
  2119.         char *port = NULL;
  2120.         char *rexxcmd = NULL;
  2121.  
  2122.         while (fgets(buf, 256, fi)) {
  2123.             if (strnicmp(buf, cmdName, strlen(cmdName)) == 0)
  2124.             cmd = ScanReplace(buf + strlen(cmdName), fullPath, ErrFile, curDirPath);
  2125.             else if (strnicmp(buf, portName, strlen(portName)) == 0)
  2126.             port = ScanReplace(buf + strlen(portName), fullPath, ErrFile, curDirPath);
  2127.             else if (strnicmp(buf, rexxCmdName, strlen(rexxCmdName)) == 0)
  2128.             rexxcmd= ScanReplace(buf + strlen(rexxCmdName), fullPath, ErrFile, curDirPath);
  2129.         }
  2130.         fclose(fi);
  2131.  
  2132.         if (Verbose) {
  2133.             printf("cmd=%s port=%s rexxcmd=%s file=%s\n",
  2134.             (cmd ? cmd : ""),
  2135.             (port ? port : ""),
  2136.             (rexxcmd ? rexxcmd : ""),
  2137.             fullPath
  2138.             );
  2139.         }
  2140.  
  2141.         Forbid();
  2142.         if (port && rexxcmd) {
  2143.             /*
  2144.             *  Attempt to run the CLI command that starts up the
  2145.             *  editor (or whatever)
  2146.             */
  2147.  
  2148.             {
  2149.             short retry = 0;
  2150.  
  2151.             while (FindPort(port) == NULL && retry < 5 && cmd) {
  2152.                 if (retry == 0)
  2153.                 Execute(cmd, NULL, NULL);
  2154.                 Delay(50);
  2155.                 ++retry;
  2156.             }
  2157.             }
  2158.  
  2159.             /*
  2160.             *  If port found place a REXX command directly to the port
  2161.             */
  2162.  
  2163.             if (FindPort(port)) {
  2164.             long ec;
  2165.  
  2166.             Permit();
  2167.             r = PlaceRexxCommandDirect(NULL,port,rexxcmd,NULL,&ec);
  2168.             Forbid();
  2169.             if (Verbose)
  2170.                 printf("R = %d %d\n", r, ec);
  2171.             ec = r;
  2172.             }
  2173.         } else if (cmd) {
  2174.             Execute(cmd, NULL, NULL);
  2175.         }
  2176.         Permit();
  2177.         if (cmd)
  2178.             free(cmd);
  2179.         if (port)
  2180.             free(port);
  2181.         if (rexxcmd)
  2182.             free(rexxcmd);
  2183.         } else {
  2184.         printf("can't open dcc:config/dcc.config\n");
  2185.         }
  2186.         free(fullPath);
  2187.     }
  2188.     free(buf);
  2189.     }
  2190.     return(r);
  2191. }
  2192.  
  2193. DoRexxCommand(msg, port, arg0, pres)
  2194. void *msg;
  2195. struct MsgPort *port;
  2196. char *arg0;
  2197. char **pres;
  2198. {
  2199.     return(20);
  2200. }
  2201.  
  2202. /*
  2203.  *  Handle %f/%e/%d/%n replacement in dcc.config
  2204.  */
  2205.  
  2206. char *
  2207. ScanReplace(buf, cFile, errFile, curDirPath)
  2208. char *buf;
  2209. char *cFile;
  2210. char *errFile;
  2211. char *curDirPath;
  2212. {
  2213.     char *s;
  2214.     char *rbuf;
  2215.     short i;
  2216.     short len;
  2217.     short dpindex;  /*    directory part index, char after directory  */
  2218.     short fpindex;  /*    file part index, char beginning file        */
  2219.  
  2220.     /*
  2221.      *    Split cFile into directory part and file part
  2222.      */
  2223.  
  2224.     for (dpindex = strlen(cFile) - 1; dpindex >= 0; --dpindex) {
  2225.     if ((cFile[dpindex] == ':') || (cFile[dpindex] == '/'))
  2226.         break;
  2227.     }
  2228.     ++dpindex;
  2229.     fpindex = dpindex;
  2230.  
  2231.     if (cFile[fpindex] == ':')
  2232.     ++fpindex;
  2233.  
  2234.     /*
  2235.      *    Actual scan
  2236.      */
  2237.  
  2238.     while (*buf == ' ' || *buf == '\t')
  2239.     ++buf;
  2240.     rbuf = NULL;
  2241.     for (i = 0; i < 2; ++i) {
  2242.     len = 0;
  2243.  
  2244.     for (s = buf; *s; ++s) {
  2245.         if (*s == '%') {
  2246.         ++s;
  2247.         switch(*s) {
  2248.         case 'f':       /*  %f - source file    */
  2249.             if (rbuf)
  2250.             sprintf(rbuf + len, "%s", cFile);
  2251.             len += strlen(cFile);
  2252.             continue;
  2253.         case 'e':       /*  %e - error file     */
  2254.             if (rbuf)
  2255.             sprintf(rbuf + len, "%s", errFile);
  2256.             len += strlen(errFile);
  2257.             continue;
  2258.         case 'd':
  2259.             if (rbuf)
  2260.             sprintf(rbuf + len, "%.*s", dpindex, cFile);
  2261.             len += dpindex;
  2262.             continue;
  2263.         case 'n':
  2264.             if (rbuf)
  2265.             sprintf(rbuf + len, "%s", cFile + fpindex);
  2266.             len += strlen(cFile + fpindex);
  2267.             continue;
  2268.         case 'c':
  2269.             if (rbuf)
  2270.             sprintf(rbuf + len, "%s", curDirPath);
  2271.             len += strlen(curDirPath);
  2272.             continue;
  2273.         case '0':
  2274.         case '1':
  2275.         case '2':
  2276.         case '3':
  2277.         case '4':
  2278.         case '5':
  2279.         case '6':
  2280.         case '7':
  2281.         case '8':
  2282.         case '9':
  2283.             {
  2284.             char *aptr = RexxReplace[*s - '0'];
  2285.  
  2286.             if (aptr == NULL)
  2287.                 aptr = "?";
  2288.             if (rbuf)
  2289.                 sprintf(rbuf + len, "%s", aptr);
  2290.             len += strlen(aptr);
  2291.             }
  2292.             continue;
  2293.         }
  2294.         --s;
  2295.         }
  2296.         if (*s == '\n')
  2297.         continue;
  2298.         if (rbuf)
  2299.         rbuf[len] = *s;
  2300.         ++len;
  2301.     }
  2302.     if (i == 0)
  2303.         rbuf = malloc(len + 1);
  2304.     }
  2305.     if (rbuf)
  2306.     rbuf[len] = 0;
  2307.     else
  2308.     rbuf = strdup("");
  2309.     return(rbuf);
  2310. }
  2311.  
  2312. char *
  2313. FullPathOf(file)
  2314. char *file;
  2315. {
  2316.     BPTR lock;
  2317.     BPTR dlock;
  2318.     __aligned FIB fib;
  2319.     char *s1 = strdup(file);
  2320.  
  2321.     if (lock = Lock(file, SHARED_LOCK))
  2322.     {
  2323.     if (Examine(lock, &fib))
  2324.     {
  2325.         short i = 0;
  2326.         free(s1);
  2327.         i = strlen(fib.fib_FileName);
  2328.         s1 = malloc(i + 2);
  2329.         strcpy(s1, fib.fib_FileName);
  2330.         s1[i+1] = '\0';  /* Ensure we have have a null terminator when we */
  2331.                          /* Insert the colon if this is the root only     */
  2332.         while (dlock = ParentDir(lock))
  2333.         {
  2334.         UnLock(lock);
  2335.         lock = dlock;
  2336.         if (Examine(lock, &fib))
  2337.         {
  2338.             char *s2;
  2339.             s2 = malloc(strlen(s1) + strlen(fib.fib_FileName) + 2);
  2340.             sprintf(s2, "%s/%s", fib.fib_FileName, s1);
  2341.             free(s1);
  2342.             s1 = s2;
  2343.             i = strlen(fib.fib_FileName);
  2344.         }
  2345.         }
  2346.         s1[i] = ':';
  2347.     }
  2348.     UnLock(lock);
  2349.     }
  2350.     return(s1);
  2351. }
  2352.  
  2353. #endif
  2354. #endif
  2355.  
  2356. /*
  2357.  *  Exit with a code, the -unixrc option causes unix style
  2358.  *  exit codes to be used (0 on no error or warning, 1 on error)
  2359.  */
  2360.  
  2361. void
  2362. uexit(int code)
  2363. {
  2364.     if (UnixRCOpt) {
  2365.     if (code <= 5)
  2366.         code = 0;
  2367.     else
  2368.         code = 1;
  2369.     }
  2370.     exit(code);
  2371. }
  2372.  
  2373. void
  2374. eprintf(const char *ctl, ...)
  2375. {
  2376.     va_list va;
  2377.  
  2378.     va_start(va, ctl);
  2379.     vfprintf(stderr, ctl, va);
  2380.     if (ErrorFi) {
  2381.     vfprintf(ErrorFi, ctl, va);
  2382.     }
  2383.     va_end(va);
  2384. }
  2385.  
  2386.